package com.wrupple.muba.common.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.rpc.IsSerializable;

/**
 * 
 * An Application's Atomic Unit of User Interaction. It holds the information to
 * start an element inside the application and allow the user to start working
 * 
 * The unique identifier, while recommended to be a
 * no-spaces-no-special-characters String, no actual checks will be done on
 * runtime to assert it.
 * 
 * 
 * @author japi
 * 
 */
public class ApplicationItem extends Place implements Serializable,
		IsSerializable {

	private static final long serialVersionUID = -7689056368151452282L;

	private String activity;

	private HashSet<String> elements;

	protected ArrayList<ApplicationItem> children;

	private Map<String, String> properties;

	/**
	 * Creates a new ApplicationItem
	 */
	public ApplicationItem() {
		super();
		this.properties = new HashMap<String, String>();
		this.elements = new HashSet<String>();
	}

	public ApplicationItem(String place) {
		this();
		this.activity = place;
	}

	/**
	 * @return machine-readable (no sapaces/special characters allowed) Unique
	 *         identifier for this Item
	 */
	public String getActivity() {
		return activity;
	}

	/**
	 * @param id
	 *            machine-readable (no sapaces/special characters allowed)
	 *            Unique identifier for this Item
	 */
	public void setActivity(String id) {
		this.activity = id;
	}

	/**
	 * @return this item's children
	 */
	public ArrayList<ApplicationItem> getChildren() {
		return children;
	}

	/**
	 * @param items
	 *            this item's children
	 */
	public void setChildren(ArrayList<ApplicationItem> items) {
		this.children = items;
	}

	/**
	 * Propperties plugins will look for when the item gets called
	 * 
	 * @param name
	 *            name of the propperty
	 * @return Propperty a String value
	 */
	public String getProperty(String name) {
		return this.properties.get(name);
	}

	/**
	 * @param name
	 *            name of the propperty
	 * @param value
	 *            value of the propperty
	 * @return
	 */
	public String getProperty(String name, String value) {
		return this.properties.put(name, value);
	}

	/**
	 * @return the map of properties
	 */
	public Map<String, String> getProperties() {
		return properties;
	}

	/**
	 * @param map
	 *            of properties the properties to set
	 */
	public void setProperties(Map<String, String> properties) {
		this.properties = properties;
	}

	public void setProperty(String name, String value) {
		this.properties.put(name, value);
	}

	public void setElements(HashSet<String> elements) {
		this.elements = elements;
	}

	public HashSet<String> getElements() {
		return elements;
	}

	public void addElement(String element) {
		elements.add(element);
	}

	public ApplicationItem copyWithoutProperties() {
		ApplicationItem item = new ApplicationItem();
		if (elements != null) {
			item.setElements(new HashSet<String>(elements));
		}
		item.setActivity(new String(activity));
		if (children != null) {
			item.setChildren(new ArrayList<ApplicationItem>(children));
		}
		return item;
	}

	public ApplicationItem cloneItem() {
		ApplicationItem item = copyWithoutProperties();
		item.setProperties(new HashMap<String, String>(properties));
		return item;
	}

	public void removeProperty(String key) {
		properties.remove(key);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((elements == null) ? 0 : elements.hashCode());
		result = prime * result
				+ ((activity == null) ? 0 : activity.hashCode());
		result = prime * result
				+ ((properties == null) ? 0 : properties.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ApplicationItem other = (ApplicationItem) obj;
		if (elements == null) {
			if (other.elements != null)
				return false;
		} else if (!elements.equals(other.elements))
			return false;
		if (activity == null) {
			if (other.activity != null)
				return false;
		} else if (!activity.equals(other.activity))
			return false;
		if (properties == null) {
			if (other.properties != null)
				return false;
		} else if (!properties.equals(other.properties))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "ApplicationItem [activity=" + activity + ", properties="
				+ properties + "]";
	}

}